package com.graduation_design.modules.search.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.graduation_design.entity.AppProduct;
import com.graduation_design.modules.search.document.EsProductDoc;
import com.graduation_design.modules.search.repository.EsProductDocRepository;
import com.graduation_design.modules.search.service.AppSearchService;
import com.graduation_design.service.AppProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AppSearchServiceImpl implements AppSearchService {

    @Resource
    AppProductService appProductService;

    @Resource
    EsProductDocRepository esProductDocRepository;

    @Resource
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    /**
     * 同步数据到es
     */
    @Override
    public int initEsData() {

        esProductDocRepository.deleteAll();

        // 查出所有的上架商品数据
        List<AppProduct> products = appProductService.list(new QueryWrapper<AppProduct>().eq("is_on_sale", true));
        // copy到EsProductDoc索引实体中
        List<EsProductDoc> docs = BeanUtil.copyToList(products, EsProductDoc.class);

        // 通过esProductDocRepository保存所有数据
        Iterable<EsProductDoc> esProductDocs = esProductDocRepository.saveAll(docs);

        int size = ListUtil.toList(esProductDocs).size();
        log.info("同步了{}条商品记录", size);
        return size;
    }

    /**
     * 搜索接口
     */
    @Override
    public Page<EsProductDoc> search(String kw, int current, int size) {

        // 使用Criteria添加查询条件，查询条件中使用matches来匹配字段与关键字的like关系，
        // 因为是2个字段，所以两个条件之间使用了or。
        Criteria criteria = new Criteria("name").matches(kw)
                .or(new Criteria("keywords").matches(kw));

        Query query = new CriteriaQuery(criteria).setPageable(PageRequest.of(current - 1, size));

        // 返回的SearchHits是命中的额查询结果
        SearchHits<EsProductDoc> searchHits = elasticsearchRestTemplate.search(query, EsProductDoc.class);

        List<EsProductDoc> productDocs = searchHits.get().map(SearchHit::getContent).collect(Collectors.toList());

        // 最后把结果集和命中的总数totalHits拼成page返回
        Page<EsProductDoc> page = new Page<>(current, size, searchHits.getTotalHits());
        page.setRecords(productDocs);
        return page;
    }

    /**
     * 更新保存
     */
    @Override
    public EsProductDoc create(Long id) {
        AppProduct appProduct = appProductService.getById(id);
        Assert.isTrue(appProduct != null, "该商品不存在");
        if(appProduct == null || !appProduct.getIsOnSale() || appProduct.getIsDelete()) {
            // 商品下架或删除了
            esProductDocRepository.deleteById(id);
        }
        EsProductDoc esProductDoc = BeanUtil.copyProperties(appProduct, EsProductDoc.class);
        log.info("正在保存商品ID:{}记录", esProductDoc.toString());
        return esProductDocRepository.save(esProductDoc);
    }

    /**
     * 更新删除
     */
    @Override
    public void delete(List<Long> ids) {
        Iterable<EsProductDoc> productDocs = esProductDocRepository.findAllById(ids);
        esProductDocRepository.deleteAll(productDocs);

        log.info("正在删除商品ID:{}记录", ids.toString());
    }

}
